// 基于正则表达式的 HTML 解析器
// 重写原有的状态机实现

/**
 * Token 类型定义
 */
const TokenType = {
    TAG_OPEN: 'tag',           // 开始标签
    TAG_CLOSE: 'tagEnd',       // 结束标签
    TEXT: 'text',              // 文本内容
    ATTRIBUTE: 'attribute',    // 属性（扩展功能）
    COMMENT: 'comment'         // 注释（扩展功能）
};

/**
 * 正则表达式模式定义
 */
const RegexPatterns = {
    // 开始标签: <tagName> 或 <tagName attributes>
    TAG_OPEN: /<([a-zA-Z][a-zA-Z0-9]*)\s*([^>]*)>/,
    
    // 结束标签: </tagName>
    TAG_CLOSE: /<\/([a-zA-Z][a-zA-Z0-9]*)\s*>/,
    
    // 文本内容: 非 < 开头的字符序列
    TEXT: /^([^<]+)/,
    
    // 注释: <!-- content -->
    COMMENT: /<!--([\s\S]*?)-->/,
    
    // 属性解析: name="value" 或 name='value' 或 name=value
    ATTRIBUTE: /([a-zA-Z][a-zA-Z0-9-]*)\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>]+))/g,
    
    // 自闭合标签: <tagName /> 或 <tagName attributes />
    SELF_CLOSING: /<([a-zA-Z][a-zA-Z0-9]*)\s*([^>]*?)\s*\/>/
};

/**
 * 基于正则表达式的词法分析器
 * @param {string} template - HTML 模板字符串
 * @returns {Array} tokens - 解析后的 token 数组
 */
function tokenizeWithRegex(template) {
    const tokens = [];
    let remaining = template.trim();
    
    while (remaining.length > 0) {
        let matched = false;
        
        // 1. 尝试匹配注释
        const commentMatch = remaining.match(RegexPatterns.COMMENT);
        if (commentMatch && commentMatch.index === 0) {
            tokens.push({
                type: TokenType.COMMENT,
                content: commentMatch[1].trim()
            });
            remaining = remaining.slice(commentMatch[0].length);
            matched = true;
            continue;
        }
        
        // 2. 尝试匹配自闭合标签
        const selfClosingMatch = remaining.match(RegexPatterns.SELF_CLOSING);
        if (selfClosingMatch && selfClosingMatch.index === 0) {
            const tagName = selfClosingMatch[1];
            const attributesStr = selfClosingMatch[2].trim();
            
            const token = {
                type: TokenType.TAG_OPEN,
                name: tagName,
                isSelfClosing: true
            };
            
            // 解析属性
            if (attributesStr) {
                token.attributes = parseAttributes(attributesStr);
            }
            
            tokens.push(token);
            remaining = remaining.slice(selfClosingMatch[0].length);
            matched = true;
            continue;
        }
        
        // 3. 尝试匹配结束标签
        const closeTagMatch = remaining.match(RegexPatterns.TAG_CLOSE);
        if (closeTagMatch && closeTagMatch.index === 0) {
            tokens.push({
                type: TokenType.TAG_CLOSE,
                name: closeTagMatch[1]
            });
            remaining = remaining.slice(closeTagMatch[0].length);
            matched = true;
            continue;
        }
        
        // 4. 尝试匹配开始标签
        const openTagMatch = remaining.match(RegexPatterns.TAG_OPEN);
        if (openTagMatch && openTagMatch.index === 0) {
            const tagName = openTagMatch[1];
            const attributesStr = openTagMatch[2].trim();
            
            const token = {
                type: TokenType.TAG_OPEN,
                name: tagName
            };
            
            // 解析属性
            if (attributesStr) {
                token.attributes = parseAttributes(attributesStr);
            }
            
            tokens.push(token);
            remaining = remaining.slice(openTagMatch[0].length);
            matched = true;
            continue;
        }
        
        // 5. 尝试匹配文本内容
        const textMatch = remaining.match(RegexPatterns.TEXT);
        if (textMatch) {
            const textContent = textMatch[1].trim();
            if (textContent) {
                tokens.push({
                    type: TokenType.TEXT,
                    content: textContent
                });
            }
            remaining = remaining.slice(textMatch[0].length);
            matched = true;
            continue;
        }
        
        // 6. 如果都没匹配到，跳过当前字符
        if (!matched) {
            remaining = remaining.slice(1);
        }
    }
    
    return tokens;
}

/**
 * 解析属性字符串
 * @param {string} attributesStr - 属性字符串
 * @returns {Object} attributes - 属性对象
 */
function parseAttributes(attributesStr) {
    const attributes = {};
    let match;
    
    // 重置正则表达式的 lastIndex
    RegexPatterns.ATTRIBUTE.lastIndex = 0;
    
    while ((match = RegexPatterns.ATTRIBUTE.exec(attributesStr)) !== null) {
        const attrName = match[1];
        const attrValue = match[2] || match[3] || match[4] || '';
        attributes[attrName] = attrValue;
    }
    
    return attributes;
}

/**
 * 简化版本的词法分析器（与原版本兼容）
 * @param {string} str - HTML 字符串
 * @returns {Array} tokens - 解析后的 token 数组
 */
function tokenizeSimple(str) {
    const tokens = [];
    
    // 使用正则表达式一次性匹配所有 token
    const tokenRegex = /<\/([a-zA-Z]+)>|<([a-zA-Z]+)>|([^<]+)/g;
    let match;
    
    while ((match = tokenRegex.exec(str)) !== null) {
        if (match[1]) {
            // 结束标签
            tokens.push({
                type: 'tagEnd',
                name: match[1]
            });
        } else if (match[2]) {
            // 开始标签
            tokens.push({
                type: 'tag',
                name: match[2]
            });
        } else if (match[3] && match[3].trim()) {
            // 文本内容
            tokens.push({
                type: 'text',
                content: match[3].trim()
            });
        }
    }
    
    return tokens;
}

// 测试代码
console.log('=== 原版本兼容测试 ===');
const simpleTokens = tokenizeSimple(`<div>hello</div>`);
console.log('%c [ simpleTokens ]', 'font-size:13px; background:lightblue; color:#1f4e79;', simpleTokens);

console.log('\n=== 增强版本测试 ===');
const complexTemplate = `
    <!-- 这是一个注释 -->
    <div class="container" id="main">
        <h1>标题</h1>
        <p>这是一段文本</p>
        <img src="image.jpg" alt="图片" />
        <input type="text" value="默认值" />
    </div>
`;

const enhancedTokens = tokenizeWithRegex(complexTemplate);
console.log('%c [ enhancedTokens ]', 'font-size:13px; background:lightgreen; color:#2d5a2d;', enhancedTokens);

// 导出函数供其他模块使用
if (typeof module !== 'undefined' && module.exports) {
    module.exports = {
        tokenizeSimple,
        tokenizeWithRegex,
        parseAttributes,
        TokenType,
        RegexPatterns
    };
}
